package com.xcc.java_base;

/**
 *
 */
public class Demo01_StringIntern {

    public static void main(String[] args) {
        testO1();
        testO2();
        testO3();
        testO4();
    }

    /**
     * 58面试真题
     * Java有静态常量池和运行时常量池的概念
     *   静态常量池存储在.class文件中
     *   运行时常量池存储在方法区中，相比于静态常量池重要特征是 具备动态性 。
     *
     * String.intern()如果字符串常量池存在字符串相等(equals() )的字符串对象，
     *   就返回此常量池中的String对象。否则将String对象添加到常量池中，并返回此String对象的引用。
     */
    /**
     *
     */
    private static void testO4() {
        System.out.println("=========test04=========");
        String str1 = new StringBuilder("58").append("tongcheng").toString();
        System.out.println(str1);
        System.out.println(str1.intern());
        System.out.println(str1 == str1.intern());

        System.out.println("------------");

        String str2 = new StringBuilder("ja").append("va").toString();
        System.out.println(str2);
        System.out.println(str2.intern());
        System.out.println(str2 == str2.intern());

        System.out.println("------------");

        String str3 = new String("xiaocheng"); //左边在栈  右边是堆(存储对象)
        System.out.println(str3);
        System.out.println(str3.intern());
        System.out.println(str3 == str3.intern());

    }

    private static void testO3() {
        System.out.println("=========test03=========");
        String str11 = new StringBuilder("xiao").append("cheng").toString();  //对象放在堆里--采用new 创建的字符串对象不进常量池
        String str22 = new StringBuilder("xiao").append("cheng").toString();  //对象放在堆里--采用new 创建的字符串对象不进常量池
        System.out.println(str11 == str22);
        System.out.println(str11 == str11.intern());        //第一次调用Intern发现字符串不存在常量池，（1.7 将str11的引用放入常量池）
        System.out.println(str11 == str22.intern());        //第二次调用Intern发现字符串存在常量池里，返回常量池里的引用

        final String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        String str4 = "a" + str2;                  //字符串相加含有变量则不会进入常量池中
        String str5 = new String("ab");
        String str6 = "a"+"b";                     //字符串相加的时候，都是静态字符串的结果会添加到常量池
        String str7 = str1 +"b" ;                   //对final变量的访问在编译期间都会直接被替代为真实的值 相当于静态字符串

        System.out.println(str5 == str3);
        System.out.println(str5.intern() == str3);
        System.out.println(str5.intern() == str4);
        System.out.println(str5.intern() == str6);
        System.out.println(str5.intern() == str7);

    }

    private static void testO2() {
        System.out.println("=========test02=========");
//        String str1 = new StringBuilder("abc").toString();
        String str1 = new StringBuilder("abc").append("bbb").toString();
        String str2 = str1.intern();
        System.out.println(str1 == str2);
    }

    /**
     * Java有静态常量池和运行时常量池的概念
     *  静态常量池存储在.class文件中
     *  运行时常量池存储在方法区中，相比于静态常量池重要特征是 具备动态性 。
     *
     *  String.intern()如果字符串常量池存在字符串相等(equals() )的字符串对象，
     *   就返回此常量池中的String对象。否则将String对象添加到常量池中，并返回此String对象的引用。
     */
    private static void testO1() {
        String a = "aaa";
        String b = "aaa";
        System.out.println(a==b);
    }

}
